home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / pcomm1.2 / part08 < prev    next >
Encoding:
Internet Message Format  |  1989-10-25  |  43.9 KB

  1. Subject:  v20i074:  Pcomm telecommunication package, Part08/08
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: fthood!egray
  7. Posting-number: Volume 20, Issue 74
  8. Archive-name: pcomm1.2/part08
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    x_menu.c
  16. #    x_rcv.c
  17. #    x_send.c
  18. #    x_win.c
  19. #    xmodem.c
  20. #    xmodem.h
  21. export PATH; PATH=/bin:/usr/bin:$PATH
  22. echo shar: "extracting 'x_menu.c'" '(7594 characters)'
  23. if test -f 'x_menu.c'
  24. then
  25.     echo shar: "will not over-write existing file 'x_menu.c'"
  26. else
  27. sed 's/^X//' << \SHAR_EOF > 'x_menu.c'
  28. X/*
  29. X * Open a window to display the choices of file transfer protocols and
  30. X * prompt for the file name(s).  A non-zero return code means turn the
  31. X * input routine back on.
  32. X */
  33. X
  34. X#include <stdio.h>
  35. X#include <sys/types.h>
  36. X#include <sys/stat.h>
  37. X#include <curses.h>
  38. X#include "config.h"
  39. X#include "extrnl.h"
  40. X#include "misc.h"
  41. X#include "xmodem.h"
  42. X
  43. Xint
  44. Xxfer_menu(up)
  45. Xint up;
  46. X{
  47. X    extern int fd;
  48. X    extern char *null_ptr;
  49. X    WINDOW *xm_win, *newwin();
  50. X    char buf[2048], *list, *get_names(), *get_extrnl(), *strcat();
  51. X    char *strcpy();
  52. X    int type, is_batch, i, ans, num_extrnl, n, ret_code;
  53. X    void xfer_win(), xfer_ascii(), do_extrnl(), error_win();
  54. X
  55. X    num_extrnl = (up) ? extrnl->up_entries : extrnl->dn_entries;
  56. X    xm_win = newwin(14+num_extrnl, 20, 2, 45);
  57. X
  58. X    mvwaddstr(xm_win, 2, 3, "1) xmodem");
  59. X    mvwaddstr(xm_win, 3, 3, "2) xmodem-1k");
  60. X    mvwaddstr(xm_win, 4, 3, "3) modem7");
  61. X    mvwaddstr(xm_win, 5, 3, "4) ymodem");
  62. X    mvwaddstr(xm_win, 6, 3, "5) ymodem-g");
  63. X    mvwaddstr(xm_win, 7, 3, "6) ASCII");
  64. X
  65. X    for (i=0; i<num_extrnl; i++)
  66. X        mvwprintw(xm_win, i+8, 3, "%d) %-12.12s", i+7, extrnl->name[up][i]);
  67. X    mvwaddstr(xm_win, i+8, 3, "E) (external)");
  68. X    mvwaddstr(xm_win, i+10, 3, "<ESC> to Abort");
  69. X    mvwaddstr(xm_win, i+11, 3, "Protocol:");
  70. X    box(xm_win, VERT, HORZ);
  71. X    if (up)
  72. X        mvwattrstr(xm_win, 0, 6, A_BOLD, " Upload ");
  73. X    else
  74. X        mvwattrstr(xm_win, 0, 5, A_BOLD, " Download ");
  75. X
  76. X    wmove(xm_win, i+11, 13);
  77. X    wrefresh(xm_win);
  78. X                    /* get the protocol */
  79. X    type = -1;
  80. X    while ((ans = wgetch(xm_win)) != ESC) {
  81. X        switch (ans) {
  82. X            case '1':
  83. X                type = XMODEM;
  84. X                break;
  85. X            case '2':
  86. X                type = XMODEM_1k;
  87. X                break;
  88. X            case '3':
  89. X                type = MODEM7;
  90. X                break;
  91. X            case '4':
  92. X                type = YMODEM;
  93. X                break;
  94. X            case '5':
  95. X                type = YMODEM_G;
  96. X                break;
  97. X            case '6':
  98. X                type = XASCII;
  99. X                break;
  100. X            case '7':
  101. X                if (num_extrnl >= 1)
  102. X                    type = EXT_1;
  103. X                else
  104. X                    beep();
  105. X                break;
  106. X            case '8':
  107. X                if (num_extrnl >= 2)
  108. X                    type = EXT_2;
  109. X                else
  110. X                    beep();
  111. X                break;
  112. X            case '9':
  113. X                if (num_extrnl >= 3)
  114. X                    type = EXT_3;
  115. X                else
  116. X                    beep();
  117. X                break;
  118. X            case 'e':
  119. X            case 'E':
  120. X                type = EXT_MANUAL;
  121. X                break;
  122. X            default:
  123. X                beep();
  124. X        }
  125. X        if (type != -1)
  126. X            break;
  127. X    }
  128. X    werase(xm_win);
  129. X    wrefresh(xm_win);
  130. X    delwin(xm_win);
  131. X                    /* chicken'd out */
  132. X    if (type == -1)
  133. X        return(0);
  134. X
  135. X    if (fd == -1) {
  136. X        error_win(0, "Not currently connected to any host", "");
  137. X        return(0);
  138. X    }
  139. X                    /* which protocol? */
  140. X    ret_code = 0;
  141. X    is_batch = 0;
  142. X    switch(type) {
  143. X        case MODEM7:
  144. X        case YMODEM:
  145. X        case YMODEM_G:        /* built-in protocols */
  146. X            is_batch++;
  147. X            /* fall thru */
  148. X        case XMODEM:
  149. X        case XMODEM_1k:        /* non-batch built-ins */
  150. X            list = null_ptr;
  151. X            /*
  152. X             * When receiving in a batch mode, don't prompt
  153. X             * for file names.
  154. X             */
  155. X            if (up || !is_batch) {
  156. X                if (!(list = get_names(up, type, is_batch)))
  157. X                    break;
  158. X            }
  159. X            xfer_win(list, up, type);
  160. X            ret_code++;
  161. X            break;
  162. X        case XASCII:        /* ascii xfer, yuck! */
  163. X            if (list = get_names(up, type, FALSE)) {
  164. X                xfer_ascii(list, up);
  165. X                if (!up)
  166. X                    ret_code++;
  167. X            }
  168. X            break;
  169. X        case EXT_1:
  170. X        case EXT_2:
  171. X        case EXT_3:        /* one of the externals */
  172. X            n = type -NUM_INTERNAL;
  173. X            strcpy(buf, extrnl->command[up][n]);
  174. X                    /* see if we need to prompt for files */
  175. X            if (extrnl->prompt[up][n] == 'Y') {
  176. X                if (list = get_names(up, type, TRUE)) {
  177. X                    strcat(buf, " ");
  178. X                    strcat(buf, list);
  179. X                }
  180. X                else
  181. X                    break;
  182. X            }
  183. X            do_extrnl(buf);
  184. X            ret_code++;
  185. X            break;
  186. X        case EXT_MANUAL:    /* the manual external protocol */
  187. X            if (list = get_extrnl(up)) {
  188. X                do_extrnl(list);
  189. X                ret_code++;
  190. X            }
  191. X            break;
  192. X    }
  193. X    return(ret_code);
  194. X}
  195. X
  196. Xchar *protocol[NUM_INTERNAL] = {"xmodem", "xmodem-1k", "modem7", "ymodem",
  197. X    "ymodem-g", "ASCII"};
  198. X
  199. X/*
  200. X * Prompt for a list of files for the transfer programs.  Since expand()
  201. X * is used, it returns a pointer to a static area.  Returns a NULL if 
  202. X * you chicken'd out.
  203. X */
  204. X
  205. Xstatic char *
  206. Xget_names(up, type, is_batch)
  207. Xint up, type, is_batch;
  208. X{
  209. X    int got_it;
  210. X    WINDOW *gn_win, *newwin();
  211. X    char *ans, *file, *list, buf[40], *expand(), *get_str(), *strtok();
  212. X    void st_line();
  213. X    struct stat stbuf;
  214. X
  215. X    touchwin(stdscr);
  216. X    refresh();
  217. X    st_line("");
  218. X
  219. X    gn_win = newwin(7, 70, 5, 5);
  220. X    mvwaddstr(gn_win, 3, 4, "Enter filename: ");
  221. X    box(gn_win, VERT, HORZ);
  222. X    if (up) {
  223. X        if (type < NUM_INTERNAL)
  224. X            sprintf(buf, " Send %s ", protocol[type]);
  225. X        else
  226. X            sprintf(buf, " Send %s ", extrnl->name[up][type-NUM_INTERNAL]);
  227. X    }
  228. X    else {
  229. X        if (type < NUM_INTERNAL)
  230. X            sprintf(buf, " Receive %s ", protocol[type]);
  231. X        else
  232. X            sprintf(buf, " Receive %s ", extrnl->name[up][type-NUM_INTERNAL]);
  233. X    }
  234. X    mvwattrstr(gn_win, 0, 3, A_BOLD, buf);
  235. X
  236. X    while (1) {
  237. X        wmove(gn_win, 3, 20);
  238. X        wrefresh(gn_win);
  239. X                    /* get the answers */
  240. X        if (is_batch)
  241. X            ans = get_str(gn_win, 60, "", "\n");
  242. X        else
  243. X            ans = get_str(gn_win, 60, "", " \t\n");
  244. X
  245. X        if (ans == NULL || *ans == '\0') {
  246. X            list = NULL;
  247. X            break;
  248. X        }
  249. X        list = expand(ans);
  250. X                    /* batches are checked on-the-fly */
  251. X        if (is_batch)
  252. X            break;
  253. X        /*
  254. X         * Here we have the opportunity to determine the read and
  255. X         * write permissions before things get started.  Much nicer
  256. X         * than finding out later when there's no way to fix it.
  257. X         * Only checks the first file.
  258. X         */
  259. X        file = strtok(list, " \t");
  260. X                    /* sanity checking */
  261. X        if (!stat(file, &stbuf)) {
  262. X            if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  263. X                beep();
  264. X                clear_line(gn_win, 4, 15, TRUE);
  265. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "Not a regular file");
  266. X                wrefresh(gn_win);
  267. X                wait_key(gn_win, 3);
  268. X                clear_line(gn_win, 4, 15, TRUE);
  269. X                clear_line(gn_win, 3, 20, TRUE);
  270. X                continue;
  271. X            }
  272. X        }
  273. X                    /* check read permission */
  274. X        if (up) {
  275. X            if (access(file, 0)) {
  276. X                beep();
  277. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "Can't find file");
  278. X                wrefresh(gn_win);
  279. X                wait_key(gn_win, 3);
  280. X                clear_line(gn_win, 4, 15, TRUE);
  281. X                clear_line(gn_win, 3, 20, TRUE);
  282. X                continue;
  283. X            }
  284. X            if (access(file, 4)) {
  285. X                beep();
  286. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "No read permission");
  287. X                wrefresh(gn_win);
  288. X                wait_key(gn_win, 3);
  289. X                clear_line(gn_win, 4, 15, TRUE);
  290. X                clear_line(gn_win, 3, 20, TRUE);
  291. X                continue;
  292. X            }
  293. X            break;
  294. X        }
  295. X                    /* check write permission */
  296. X        got_it = 0;
  297. X        switch(can_write(file)) {
  298. X            case DENIED:
  299. X                beep();
  300. X                clear_line(gn_win, 4, 15, TRUE);
  301. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "No write permission");
  302. X                wrefresh(gn_win);
  303. X                wait_key(gn_win, 3);
  304. X                clear_line(gn_win, 4, 15, TRUE);
  305. X                clear_line(gn_win, 3, 20, TRUE);
  306. X                break;
  307. X            case OK_BUT_EXISTS:
  308. X                if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) {
  309. X                    clear_line(gn_win, 4, 15, TRUE);
  310. X                    clear_line(gn_win, 3, 20, TRUE);
  311. X                    break;
  312. X                }
  313. X                /* fall thru */
  314. X            case WRITE_OK:
  315. X                got_it++;
  316. X                break;
  317. X        }
  318. X        if (got_it)
  319. X            break;
  320. X    }
  321. X    werase(gn_win);
  322. X    wrefresh(gn_win);
  323. X    delwin(gn_win);
  324. X
  325. X    return(list);
  326. X}
  327. X
  328. X/*
  329. X * Prompt for the Unix command line to be used as an external file
  330. X * transfer program.  Since expand() is used, it returns a pointer to
  331. X * a static area.
  332. X */
  333. X
  334. Xstatic char *
  335. Xget_extrnl(up)
  336. Xint up;
  337. X{
  338. X    WINDOW *ge_win, *newwin();
  339. X    char *ans, *cmd, *get_str(), *expand();
  340. X    void st_line();
  341. X
  342. X    touchwin(stdscr);
  343. X    refresh();
  344. X    st_line("");
  345. X                    /* prompt for command line */
  346. X    ge_win = newwin(7, 70, 5, 5);
  347. X    mvwaddstr(ge_win, 3, 4, "Enter Unix command: ");
  348. X    box(ge_win, VERT, HORZ);
  349. X
  350. X    if (up)
  351. X        mvwattrstr(ge_win, 0, 3, A_BOLD, " Send (external) ");
  352. X    else
  353. X        mvwattrstr(ge_win, 0, 3, A_BOLD, " Receive (external) ");
  354. X
  355. X    wmove(ge_win, 3, 24);
  356. X    wrefresh(ge_win);
  357. X                    /* get the line */
  358. X    ans = get_str(ge_win, 60, "", "\n");
  359. X    if (ans == NULL || *ans == '\0')
  360. X        cmd = NULL;
  361. X    else
  362. X        cmd = expand(ans);
  363. X
  364. X    werase(ge_win);
  365. X    wrefresh(ge_win);
  366. X    delwin(ge_win);
  367. X    return(cmd);
  368. X}
  369. SHAR_EOF
  370. if test 7594 -ne "`wc -c < 'x_menu.c'`"
  371. then
  372.     echo shar: "error transmitting 'x_menu.c'" '(should have been 7594 characters)'
  373. fi
  374. fi
  375. echo shar: "extracting 'x_rcv.c'" '(12008 characters)'
  376. if test -f 'x_rcv.c'
  377. then
  378.     echo shar: "will not over-write existing file 'x_rcv.c'"
  379. else
  380. sed 's/^X//' << \SHAR_EOF > 'x_rcv.c'
  381. X/*
  382. X * Receive a list of files using a version of Ward Christensen's file
  383. X * transfer protocol.  A non-zero return code means the user must acknowledge
  384. X * an error condition (a user generated abort returns a 0).  Write errors
  385. X * are considered fatal.
  386. X */
  387. X
  388. X#include <stdio.h>
  389. X#include <curses.h>
  390. X#include "config.h"
  391. X#include "dial_dir.h"
  392. X#include "misc.h"
  393. X#include "xmodem.h"
  394. X
  395. Xunsigned char buf[1029];
  396. Xchar file_name[15];
  397. Xlong file_length;
  398. X
  399. Xstatic int err_method, tot_err, block_size;
  400. X
  401. Xint
  402. Xrcv_xmodem(win, list, type, fast)
  403. XWINDOW *win;
  404. Xchar *list;
  405. Xint type, fast;
  406. X{
  407. X    extern char *protocol[];
  408. X    FILE *fp, *my_fopen();
  409. X    int i, default_err, is_batch, max_block, code, file_count, got_hdr;
  410. X    int hours, mins, secs, len;
  411. X    long block, recv;
  412. X    float percent, performance;
  413. X    unsigned char blk;
  414. X    unsigned int sleep();
  415. X    char *file, *name, *strcpy(), *strrchr(), *strtok();
  416. X    void cancel_xfer();
  417. X                    /* which protocol? */
  418. X    switch (type) {
  419. X        case XMODEM:
  420. X            default_err = CRC_CHECKSUM;
  421. X            is_batch = 0;
  422. X            max_block = 128;
  423. X            break;
  424. X        case XMODEM_1k:
  425. X            default_err = CRC_CHECKSUM;
  426. X            is_batch = 0;
  427. X            max_block = 1024;
  428. X            break;
  429. X        case MODEM7:
  430. X            default_err = CHECKSUM;
  431. X            is_batch = 1;
  432. X            max_block = 128;
  433. X            break;
  434. X        case YMODEM:
  435. X            default_err = CRC;
  436. X            is_batch = 1;
  437. X            max_block = 1024;
  438. X            performance = 1.09;
  439. X            break;
  440. X        case YMODEM_G:
  441. X            default_err = NONE;
  442. X            is_batch = 1;
  443. X            max_block = 1024;
  444. X            performance = 1.02;
  445. X            break;
  446. X        default:
  447. X            return(1);
  448. X    }
  449. X
  450. X    tot_err = 0;
  451. X    file_count = 0;
  452. X    mvwaddstr(win, 2, 24, protocol[type]);
  453. X    mvwaddstr(win, 11, 24, "0  ");
  454. X
  455. X    while (1) {
  456. X        file_count++;
  457. X        file_length = 0L;
  458. X                    /* user supplied name */
  459. X        if (!is_batch) {
  460. X            if (file_count > 1)
  461. X                break;
  462. X
  463. X            file = strtok(list, " \t");
  464. X                    /* dissect the file name */
  465. X            if ((name = strrchr(file, '/')))
  466. X                strcpy(file_name, ++name);
  467. X            else
  468. X                strcpy(file_name, file);
  469. X        }
  470. X                    /* get the modem7 file name */
  471. X        if (type == MODEM7) {
  472. X            if (code = rcv_modem7(win, default_err))
  473. X                return(code +1);
  474. X
  475. X            file = file_name;
  476. X        }
  477. X                    /* get the block 0 */
  478. X        if (type == YMODEM || type == YMODEM_G) {
  479. X            if (code = send_first(win, max_block, default_err))
  480. X                return(code +1);
  481. X
  482. X            if (code = rcv_ymodem(win))
  483. X                return(code +1);
  484. X
  485. X                    /* at the end? */
  486. X            if (buf[3] == '\0') {
  487. X                beep();
  488. X                wrefresh(win);
  489. X                putc_line(ACK);
  490. X                sleep(1);
  491. X                return(0);
  492. X            }
  493. X            file = file_name;
  494. X        }
  495. X                    /* any trouble? */
  496. X        if (file_name[0] == '\0')
  497. X            continue;
  498. X
  499. X        clear_line(win, 3, 24, TRUE);
  500. X        waddstr(win, file_name);
  501. X                    /* if file length is known */
  502. X        if (file_length != 0L) {
  503. X            mvwprintw(win, 4, 24, "%-10ld", file_length);
  504. X
  505. X            secs = (file_length * 10.0 / dir->baud[dir->d_cur]) * performance;
  506. X            hours = secs / 3600;
  507. X            mins = (secs % 3600) / 60;
  508. X            secs = (secs % 3600) % 60;
  509. X
  510. X            mvwprintw(win, 6, 24, "%d:%02d:%02d", hours, mins, secs);
  511. X        }
  512. X                    /* some starting numbers */
  513. X        mvwaddstr(win, 7, 24, "0    ");
  514. X        if (file_length != 0L && fast)
  515. X            mvwaddstr(win, 8, 24, "0%  ");
  516. X        if (fast)
  517. X            mvwaddstr(win, 9, 24, "0          ");
  518. X        mvwaddstr(win, 10, 24, "0 ");
  519. X        clear_line(win, 12, 24, TRUE);
  520. X        waddstr(win, "NONE");
  521. X        wrefresh(win);
  522. X
  523. X        /*
  524. X         * If the user supplied the name, write permission is checked
  525. X         * by the get_names() routine in xfer_menu().  If modem7
  526. X         * or ymodem supplied name, the name is unique and the write
  527. X         * permission on the directory is checked by the change_name()
  528. X         * routines.  However, this is required for systems with
  529. X         * SETUID_BROKE set.
  530. X         */
  531. X                    /* open the file */
  532. X        if (!(fp = my_fopen(file, "w"))) {
  533. X            beep();
  534. X            clear_line(win, 12, 24, TRUE);
  535. X            wattrstr(win, A_BOLD, "CAN'T OPEN FILE");
  536. X            wrefresh(win);
  537. X            cancel_xfer(DOWN_LOAD);
  538. X            return(1);
  539. X        }
  540. X                    /* ACK the block 0 */
  541. X        if (type == YMODEM || type == YMODEM_G)
  542. X            putc_line(ACK);
  543. X
  544. X        if (code = send_first(win, max_block, default_err)) {
  545. X            fclose(fp);
  546. X            return(code +1);
  547. X        }
  548. X                    /* here we go... */
  549. X        clear_line(win, 12, 24, TRUE);
  550. X        waddstr(win, "NONE");
  551. X        wrefresh(win);
  552. X        blk = 1;
  553. X        block = 1L;
  554. X        recv = 0L;
  555. X        got_hdr = 1;
  556. X        while (1) {
  557. X            code = rcv_block(win, got_hdr, max_block, blk);
  558. X
  559. X            if (code < 0) {
  560. X                fclose(fp);
  561. X                return(code +1);
  562. X            }
  563. X            got_hdr = 0;
  564. X                    /* are we done? */
  565. X            if (buf[0] == EOT) {
  566. X                if (!is_batch) {
  567. X                    beep();
  568. X                    wrefresh(win);
  569. X                    sleep(1);
  570. X                }
  571. X                break;
  572. X            }
  573. X                    /* if not a duplicate block */
  574. X            if (!code) {
  575. X                if (file_length != 0L) {
  576. X                    len = file_length - recv;
  577. X                    if (len > block_size)
  578. X                        len = block_size;
  579. X                }
  580. X                else
  581. X                    len = block_size;
  582. X
  583. X                if (fwrite((char *) &buf[3], sizeof(char), len, fp) != len) {
  584. X                    beep();
  585. X                    clear_line(win, 12, 24, TRUE);
  586. X                    wattrstr(win, A_BOLD, "WRITE ERROR");
  587. X                    wrefresh(win);
  588. X                    cancel_xfer(DOWN_LOAD);
  589. X                    fclose(fp);
  590. X                    /* fatal */
  591. X                    return(1);
  592. X                }
  593. X                mvwprintw(win, 7, 24, "%-5ld", block);
  594. X                recv = recv + (unsigned int) len;
  595. X                if (fast)
  596. X                    mvwprintw(win, 9, 24, "%-10ld", recv);
  597. X                blk++;
  598. X                block++;
  599. X            }
  600. X            /*
  601. X             * If the length is known, give the same status
  602. X             * report as uploading
  603. X             */
  604. X            if (file_length != 0L && fast) {
  605. X                percent = recv * 100.0 / file_length;
  606. X                if (percent > 100.0)
  607. X                    percent = 100.0;
  608. X                mvwprintw(win, 8, 24, "%0.1f%%", percent);
  609. X            }
  610. X            wrefresh(win);
  611. X            putc_line(ACK);
  612. X        }
  613. X        if (file_length != 0L && fast) {
  614. X            mvwaddstr(win, 8, 24, "100%  ");
  615. X            wrefresh(win);
  616. X        }
  617. X        /*
  618. X         * If the file length is not known, search backwards from
  619. X         * the end of the file until you find a character that is
  620. X         * not the ^Z padding character.
  621. X         */
  622. X        if (file_length == 0L) {
  623. X            for (i=block_size+2; i>2; i--) {
  624. X                if (buf[i] != CTRLZ)
  625. X                    break;
  626. X            }
  627. X            file_length = recv - (unsigned int) block_size + (unsigned int) i -2L;
  628. X            fclose(fp);
  629. X            if (fix_length(file, file_length)) {
  630. X                beep();
  631. X                clear_line(win, 12, 24, TRUE);
  632. X                wattrstr(win, A_BOLD, "TRUNCATE ERROR");
  633. X                wrefresh(win);
  634. X                    /* fatal */
  635. X                return(1);
  636. X            }
  637. X        }
  638. X        else
  639. X            fclose(fp);
  640. X                    /* ACK the EOT */
  641. X        putc_line(ACK);
  642. X    }
  643. X    return(0);
  644. X}
  645. X
  646. X/*
  647. X * Send the first character to start the transmission and set the error
  648. X * checking method.  Returns the standard error codes or 0 on success.
  649. X * The variables err_method and block_size are global.
  650. X */
  651. X
  652. Xstatic int
  653. Xsend_first(win, max_block, default_err)
  654. XWINDOW *win;
  655. Xint max_block, default_err;
  656. X{
  657. X    int i, err_count;
  658. X    unsigned int sleep();
  659. X    void cancel_xfer();
  660. X                    /* default error method */
  661. X    err_method = default_err;
  662. X    if (default_err == CRC_CHECKSUM)
  663. X        err_method = CRC;
  664. X                    /* send the first char */
  665. X    err_count = 0;
  666. X    while (err_count < MAX_ERRORS*2) {
  667. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  668. X
  669. X                    /* check for keyboard abort */
  670. X        if (wgetch(win) == ESC) {
  671. X            beep();
  672. X            clear_line(win, 12, 24, TRUE);
  673. X            waddstr(win, "ABORTED");
  674. X            wrefresh(win);
  675. X            cancel_xfer(DOWN_LOAD);
  676. X            sleep(3);
  677. X            return(ABORT);
  678. X        }
  679. X                    /* switch to checksum? */
  680. X        if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2)
  681. X            err_method = CHECKSUM;
  682. X
  683. X                    /* send error method code */
  684. X        clear_line(win, 5, 24, TRUE);
  685. X        switch (err_method) {
  686. X            case CHECKSUM:
  687. X                waddstr(win, "CHECKSUM");
  688. X                putc_line(NAK);
  689. X                break;
  690. X            case CRC:
  691. X                waddstr(win, "CRC");
  692. X                putc_line('C');
  693. X                break;
  694. X            case NONE:
  695. X                waddstr(win, "NONE");
  696. X                putc_line('G');
  697. X                break;
  698. X        }
  699. X        /*
  700. X         * We've cut the delay time in half, so we double
  701. X         * the allowable errors
  702. X         */
  703. X        if ((i = getc_line(5)) == -1) {
  704. X            err_count++;
  705. X            clear_line(win, 12, 24, TRUE);
  706. X            waddstr(win, "NO RESPONSE");
  707. X            wrefresh(win);
  708. X            continue;
  709. X        }
  710. X        buf[0] = i;
  711. X#ifdef DEBUG
  712. X        fprintf(stderr, "send_first: got header %02x, %03o, %d\n", buf[0], buf[0], buf[0]);
  713. X#endif /* DEBUG */
  714. X
  715. X        switch (buf[0]) {
  716. X            case SOH:    /* small block follows */
  717. X                block_size = 128;
  718. X                return(0);
  719. X            case STX:    /* large block follows */
  720. X                if (max_block == 1024) {
  721. X                    block_size = 1024;
  722. X                    return(0);
  723. X                }
  724. X                /* fall thru */
  725. X            default:
  726. X                err_count++;
  727. X                clear_line(win, 12, 24, TRUE);
  728. X                waddstr(win, "BAD HEADER");
  729. X                wrefresh(win);
  730. X                    /* read some garbage... */
  731. X                while(fread_line(buf, 1028, 1) != -1)
  732. X                    ;
  733. X                putc_line(NAK);
  734. X                break;
  735. X        }
  736. X    }
  737. X    beep();
  738. X    clear_line(win, 12, 24, TRUE);
  739. X    wattrstr(win, A_BOLD, "TIMED OUT");
  740. X    wrefresh(win);
  741. X    return(ERROR);
  742. X}
  743. X
  744. X/*
  745. X * Receive a block of info from the host.  Returns a 0 on success, a 1 on
  746. X * a duplicate block or the standard error codes.  The variables
  747. X * err_method and block_size are global.
  748. X */
  749. X
  750. Xint
  751. Xrcv_block(win, got_hdr, max_block, blk)
  752. XWINDOW *win;
  753. Xint got_hdr, max_block;
  754. Xunsigned char blk;
  755. X{
  756. X    int i, err_count, bad_block, out_of_sync;
  757. X    unsigned short crc, calc_crc();
  758. X    unsigned int packet, sleep();
  759. X    unsigned char blk_compliment, calc_sum(), crc_1, crc_2;
  760. X    void cancel_xfer();
  761. X
  762. X    err_count = 0;
  763. X    while (err_count < MAX_ERRORS) {
  764. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  765. X        mvwprintw(win, 11, 24, "%-3d", tot_err);
  766. X
  767. X                    /* scan the keyboard for abort */
  768. X        if (wgetch(win) == ESC) {
  769. X            beep();
  770. X            clear_line(win, 12, 24, TRUE);
  771. X            waddstr(win, "ABORTED");
  772. X            wrefresh(win);
  773. X            cancel_xfer(DOWN_LOAD);
  774. X            sleep(3);
  775. X            return(ABORT);
  776. X        }
  777. X                    /* have we already got a hdr? */
  778. X        if (!got_hdr) {
  779. X            if ((i = getc_line(10)) == -1) {
  780. X                err_count++;
  781. X                tot_err++;
  782. X                clear_line(win, 12, 24, TRUE);
  783. X                waddstr(win, "NO RESPONSE");
  784. X                wrefresh(win);
  785. X                continue;
  786. X            }
  787. X            buf[0] = i;
  788. X#ifdef DEBUG
  789. X            fprintf(stderr, "rcv_block: got header %02x, %03o, %d\n", buf[0], buf[0], buf[0]);
  790. X#endif /* DEBUG */
  791. X                    /* what'd we get? */
  792. X            switch (buf[0]) {
  793. X                case EOT:    /* we're done! */
  794. X                    clear_line(win, 12, 24, TRUE);
  795. X                    waddstr(win, "TRANSFER COMPLETE");
  796. X                    wrefresh(win);
  797. X                    sleep(1);
  798. X                    return(0);
  799. X                case SOH:    /* small block follows */
  800. X                    block_size = 128;
  801. X                    break;
  802. X                case STX:    /* large block follows */
  803. X                    if (max_block == 1024) {
  804. X                        block_size = 1024;
  805. X                        break;
  806. X                    }
  807. X                    /* fall thru... */
  808. X                default:
  809. X                    err_count++;
  810. X                    tot_err++;
  811. X                    clear_line(win, 12, 24, TRUE);
  812. X                    waddstr(win, "BAD HEADER");
  813. X                    wrefresh(win);
  814. X
  815. X                    /* read some garbage... */
  816. X                    while(fread_line(buf, 1028, 1) != -1)
  817. X                        ;
  818. X                    putc_line(NAK);
  819. X                    continue;
  820. X            }
  821. X        }
  822. X                    /* read the rest of the packet */
  823. X        packet = block_size + 2 + (err_method == CHECKSUM ? 1 : 2);
  824. X        if (fread_line(&buf[1], packet, 10) == -1) {
  825. X            clear_line(win, 12, 24, TRUE);
  826. X            waddstr(win, "TIMED OUT");
  827. X            wrefresh(win);
  828. X            putc_line(NAK);
  829. X            err_count++;
  830. X            tot_err++;
  831. X            continue;
  832. X        }
  833. X
  834. X        /*
  835. X         * Validation of the packet includes checking the
  836. X         * block number, its complement, and the crc/checksum.
  837. X         */
  838. X        out_of_sync = 0;
  839. X        blk_compliment = ~blk;
  840. X        if (buf[1] != blk || buf[2] != blk_compliment)
  841. X            out_of_sync++;
  842. X
  843. X        bad_block = 0;
  844. X        switch (err_method) {
  845. X            case CHECKSUM:
  846. X#ifdef DEBUG
  847. X                fprintf(stderr, "blk=%d, checksum=%d\n", blk, calc_sum(&buf[3], block_size));
  848. X#endif /* DEBUG */
  849. X                if (buf[block_size +3] != calc_sum(&buf[3], block_size))
  850. X                    bad_block++;
  851. X                break;
  852. X            case CRC:
  853. X                crc = calc_crc(&buf[3], block_size);
  854. X                crc_1 = crc >> 8;
  855. X                crc_2 = crc;
  856. X#ifdef DEBUG
  857. X                fprintf(stderr, "blk=%d, crc1=%d, crc2=%d\n", blk, crc_1, crc_2);
  858. X#endif /* DEBUG */
  859. X                if (buf[block_size +3] != crc_1 || buf[block_size +4] != crc_2)
  860. X                    bad_block++;
  861. X                break;
  862. X            case NONE:
  863. X                return(0);
  864. X        }
  865. X                    /* handle errors */
  866. X        if (bad_block) {
  867. X            clear_line(win, 12, 24, TRUE);
  868. X            if (err_method == CRC)
  869. X                waddstr(win, "CRC FAILED");
  870. X            else
  871. X                waddstr(win, "CHECKSUM FAILED");
  872. X            wrefresh(win);
  873. X            putc_line(NAK);
  874. X            err_count++;
  875. X            tot_err++;
  876. X            continue;
  877. X        }
  878. X                    /* not really an error */
  879. X        if (out_of_sync) {
  880. X            /*
  881. X             * If a perfect packet is off by 1 block number,
  882. X             * (a lost ACK could cause this) then treat it as
  883. X             * a good block but don't write it to disk.
  884. X             */
  885. X            if (buf[1] == (unsigned char) blk-1)
  886. X                return(1);
  887. X
  888. X            clear_line(win, 12, 24, TRUE);
  889. X            waddstr(win, "OUT OF SYNC");
  890. X            wrefresh(win);
  891. X            putc_line(NAK);
  892. X            err_count++;
  893. X            tot_err++;
  894. X            continue;
  895. X        }
  896. X        return(0);
  897. X    }
  898. X    beep();
  899. X    clear_line(win, 12, 24, TRUE);
  900. X    waddstr(win, "TOO MANY ERRORS");
  901. X    wrefresh(win);
  902. X    cancel_xfer(DOWN_LOAD);
  903. X    return(ERROR);
  904. X}
  905. SHAR_EOF
  906. if test 12008 -ne "`wc -c < 'x_rcv.c'`"
  907. then
  908.     echo shar: "error transmitting 'x_rcv.c'" '(should have been 12008 characters)'
  909. fi
  910. fi
  911. echo shar: "extracting 'x_send.c'" '(11650 characters)'
  912. if test -f 'x_send.c'
  913. then
  914.     echo shar: "will not over-write existing file 'x_send.c'"
  915. else
  916. sed 's/^X//' << \SHAR_EOF > 'x_send.c'
  917. X/*
  918. X * Send a list of files using a version of Ward Christensen's file
  919. X * transfer protocol.  A non-zero return code means an error must be
  920. X * acknowledged by the user (a user generated abort returns a 0).
  921. X */
  922. X
  923. X#include <stdio.h>
  924. X#include <curses.h>
  925. X#include <sys/types.h>
  926. X#include <sys/stat.h>
  927. X#include "config.h"
  928. X#include "dial_dir.h"
  929. X#include "misc.h"
  930. X#include "xmodem.h"
  931. X
  932. Xstatic int tot_err, err_method;
  933. X
  934. Xint
  935. Xsend_xmodem(win, list, type, fast)
  936. XWINDOW *win;
  937. Xchar *list;
  938. Xint type, fast;
  939. X{
  940. X    extern char *protocol[];
  941. X    FILE *fp, *my_fopen();
  942. X    int i, block_size, file_count, secs, mins, hours, big_blocks;
  943. X    int small_blocks, err_count, got_it, num, is_batch, code;
  944. X    int max_block, default_err;
  945. X    long size, block, sent, xmit_size;
  946. X    char *file, *strtok(), *name, *strrchr();
  947. X    unsigned short crc, calc_crc();
  948. X    unsigned char buf[1029], blk, calc_sum();
  949. X    unsigned int packet, sleep();
  950. X    float performance, percent;
  951. X    struct stat stbuf;
  952. X                    /* which protocol? */
  953. X    switch (type) {
  954. X        case XMODEM:
  955. X            is_batch = 0;
  956. X            default_err = CRC_CHECKSUM;
  957. X            max_block = 128;
  958. X            performance = 1.36;
  959. X            break;
  960. X        case XMODEM_1k:
  961. X            is_batch = 0;
  962. X            default_err = CRC_CHECKSUM;
  963. X            max_block = 1024;
  964. X            performance = 1.09;
  965. X            break;
  966. X        case MODEM7:
  967. X            is_batch = 1;
  968. X            default_err = CHECKSUM;
  969. X            max_block = 128;
  970. X            performance = 1.36;
  971. X            break;
  972. X        case YMODEM:
  973. X            is_batch = 1;
  974. X            default_err = CRC;
  975. X            max_block = 1024;
  976. X            performance = 1.09;
  977. X            break;
  978. X        case YMODEM_G:
  979. X            is_batch = 1;
  980. X            default_err = NONE;
  981. X            max_block = 1024;
  982. X            performance = 1.02;
  983. X            break;
  984. X        default:
  985. X            return(1);
  986. X    }
  987. X
  988. X    tot_err = 0;
  989. X    file_count = 0;
  990. X    mvwaddstr(win, 2, 24, protocol[type]);
  991. X    mvwaddstr(win, 11, 24, "0  ");
  992. X
  993. X                    /* each one in the list */
  994. X    file = strtok(list, " \t");
  995. X    do {
  996. X                    /* is it a batch type? */
  997. X        file_count++;
  998. X        if (file_count > 1 && !is_batch)
  999. X            break;
  1000. X                    /* display the name */
  1001. X        clear_line(win, 3, 24, TRUE);
  1002. X        if ((name = strrchr(file, '/')))
  1003. X            name++;
  1004. X        else
  1005. X            name = file;
  1006. X        waddstr(win, name);
  1007. X        wrefresh(win);
  1008. X                    /* get the file size */
  1009. X        if (stat(file, &stbuf) < 0) {
  1010. X            beep();
  1011. X            clear_line(win, 12, 24, TRUE);
  1012. X            wattrstr(win, A_BOLD, "CAN'T FIND FILE");
  1013. X            wrefresh(win);
  1014. X            sleep(3);
  1015. X            continue;
  1016. X        }
  1017. X                    /* sanity checking */
  1018. X        if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  1019. X            beep();
  1020. X            clear_line(win, 12, 24, TRUE);
  1021. X            wattrstr(win, A_BOLD, "NOT REGULAR FILE");
  1022. X            wrefresh(win);
  1023. X            sleep(3);
  1024. X            continue;
  1025. X        }
  1026. X
  1027. X        size = stbuf.st_size;
  1028. X        mvwprintw(win, 4, 24, "%-10ld", size);
  1029. X        clear_line(win, 5, 24, TRUE);
  1030. X
  1031. X        if (!(fp = my_fopen(file, "r"))) {
  1032. X            beep();
  1033. X            clear_line(win, 12, 24, TRUE);
  1034. X            wattrstr(win, A_BOLD, "PERMISSION DENIED");
  1035. X            wrefresh(win);
  1036. X            sleep(3);
  1037. X            continue;
  1038. X        }
  1039. X                    /* get the xmit size */
  1040. X        block_size = max_block;
  1041. X        big_blocks = 0;
  1042. X        small_blocks = 0;
  1043. X        if (block_size == 128) {
  1044. X            small_blocks = size / 128;
  1045. X            if (size % 128)
  1046. X                small_blocks++;
  1047. X        }
  1048. X        else {
  1049. X            big_blocks = size / 1024;
  1050. X            small_blocks = (size % 1024) / 128;
  1051. X            if (size % 128)
  1052. X                small_blocks++;
  1053. X
  1054. X            if (small_blocks == 8 && !big_blocks) {
  1055. X                big_blocks++;
  1056. X                small_blocks = 0;
  1057. X            }
  1058. X                    /* if tiny file */
  1059. X            if (big_blocks == 0)
  1060. X                block_size = 128;
  1061. X        }
  1062. X
  1063. X        xmit_size = ((unsigned int) big_blocks * 1024L) + ((unsigned int) small_blocks * 128L);
  1064. X                    /* add block 0 to the size */
  1065. X        if (type == YMODEM || type == YMODEM_G)
  1066. X            xmit_size += 128L;
  1067. X
  1068. X        secs = (xmit_size * 10.0 / dir->baud[dir->d_cur]) * performance;
  1069. X        hours = secs / 3600;
  1070. X        mins = (secs % 3600) / 60;
  1071. X        secs = (secs % 3600) % 60;
  1072. X
  1073. X        mvwprintw(win, 6, 24, "%d:%02d:%02d", hours, mins, secs);
  1074. X
  1075. X                    /* some starting numbers */
  1076. X        mvwaddstr(win, 7, 24, "     ");
  1077. X        mvwaddstr(win, 8, 24, "0%  ");
  1078. X        mvwaddstr(win, 9, 24, "0          ");
  1079. X        mvwaddstr(win, 10, 24, "0 ");
  1080. X        clear_line(win, 12, 24, TRUE);
  1081. X        waddstr(win, "NONE");
  1082. X        wrefresh(win);
  1083. X                    /* send the batch stuff */
  1084. X        switch (type) {
  1085. X            case MODEM7:
  1086. X                if (code = rcv_first(win, default_err)) {
  1087. X                    fclose(fp);
  1088. X                    return(code +1);
  1089. X                }
  1090. X
  1091. X                if (send_modem7(win, name)) {
  1092. X                    fclose(fp);
  1093. X                    return(1);
  1094. X                }
  1095. X                break;
  1096. X            case YMODEM:
  1097. X            case YMODEM_G:
  1098. X                if (code = rcv_first(win, default_err)) {
  1099. X                    fclose(fp);
  1100. X                    return(code +1);
  1101. X                }
  1102. X
  1103. X                if (code = send_ymodem(win, name, size)) {
  1104. X                    fclose(fp);
  1105. X                    /*
  1106. X                     * CANCEL now means that the other
  1107. X                     * end can't open that file.
  1108. X                     */
  1109. X                    if (code == CANCEL)
  1110. X                        break;
  1111. X                    return(code +1);
  1112. X                }
  1113. X                xmit_size -= 128L;
  1114. X                break;
  1115. X            default:
  1116. X                code = 0;
  1117. X                break;
  1118. X        }
  1119. X                    /* remote can't receive that file? */
  1120. X        if (code == CANCEL)
  1121. X            break;
  1122. X                    /* wait for first character */
  1123. X        if (code = rcv_first(win, default_err)) {
  1124. X            fclose(fp);
  1125. X            return(code +1);
  1126. X        }
  1127. X                    /* here we go... */
  1128. X        clear_line(win, 12, 24, TRUE);
  1129. X        waddstr(win, "NONE");
  1130. X        wrefresh(win);
  1131. X        sent = 0L;
  1132. X        block = 1L;
  1133. X        blk = 1;
  1134. X        while (num = fread((char *) &buf[3], sizeof(char), block_size, fp)) {
  1135. X
  1136. X                    /* fill short block */
  1137. X            if (num < block_size) {
  1138. X                for (i=num; i<block_size; i++)
  1139. X                    buf[i+3] = CTRLZ;
  1140. X            }
  1141. X
  1142. X                    /* show current stats */
  1143. X            mvwprintw(win, 7, 24, "%-5ld", block);
  1144. X            if (fast) {
  1145. X                percent = sent * 100.0 / xmit_size;
  1146. X                mvwprintw(win, 8, 24, "%0.1f%%", percent);
  1147. X                mvwprintw(win, 9, 24, "%-10ld", sent);
  1148. X            }
  1149. X            wrefresh(win);
  1150. X
  1151. X                    /* build the header */
  1152. X            if (block_size == 128)
  1153. X                buf[0] = SOH;
  1154. X            else
  1155. X                buf[0] = STX;
  1156. X
  1157. X            buf[1] = blk;
  1158. X            buf[2] = ~blk;
  1159. X
  1160. X                    /* build the error detection stuff */
  1161. X            switch (err_method) {
  1162. X                case CHECKSUM:
  1163. X                    buf[block_size+3] = calc_sum(&buf[3], block_size);
  1164. X#ifdef DEBUG
  1165. X                    fprintf(stderr, "blk=%d, checksum=%d\n", blk, buf[block_size+3]);
  1166. X#endif /* DEBUG */
  1167. X                    packet = block_size +4;
  1168. X                    break;
  1169. X                case CRC:
  1170. X                    crc = calc_crc(&buf[3], block_size);
  1171. X                    buf[block_size+3] = crc >> 8;
  1172. X                    buf[block_size+4] = crc;
  1173. X#ifdef DEBUG
  1174. X                    fprintf(stderr, "blk=%d, crc1=%d, crc2=%d\n", blk, buf[block_size+3], buf[block_size+4]);
  1175. X#endif /* DEBUG */
  1176. X                    packet = block_size +5;
  1177. X                    break;
  1178. X                case NONE:
  1179. X                    buf[block_size+3] = 0;
  1180. X                    buf[block_size+4] = 0;
  1181. X                    packet = block_size +5;
  1182. X                    break;
  1183. X            }
  1184. X
  1185. X                    /* send the block */
  1186. X            if (code = send_block(win, buf, packet)) {
  1187. X                fclose(fp);
  1188. X                return(code +1);
  1189. X            }
  1190. X            block++;
  1191. X            blk++;
  1192. X            sent = sent + (unsigned int) block_size;
  1193. X
  1194. X                    /* change block size? */
  1195. X            if (xmit_size - sent < 1024)
  1196. X                block_size = 128;
  1197. X        }
  1198. X        mvwaddstr(win, 8, 24, "100%  ");
  1199. X        mvwprintw(win, 9, 24, "%-10ld", sent);
  1200. X                    /* at the end of the file */
  1201. X        err_count = 0;
  1202. X        got_it = 0;
  1203. X        while (err_count < MAX_ERRORS) {
  1204. X            putc_line(EOT);
  1205. X            if (getc_line(10) == ACK) {
  1206. X                got_it++;
  1207. X                break;
  1208. X            }
  1209. X            err_count++;
  1210. X        }
  1211. X        clear_line(win, 12, 24, TRUE);
  1212. X        if (!got_it) {
  1213. X            /*
  1214. X             * So what???  We don't do anything if there is
  1215. X             * no acknowledge from the host!!
  1216. X             */
  1217. X            waddstr(win, "NO ACKNOWLEDGE");
  1218. X        }
  1219. X        else
  1220. X            waddstr(win, "TRANSFER COMPLETE");
  1221. X        if (!is_batch)
  1222. X            beep();
  1223. X        wrefresh(win);
  1224. X        sleep(2);
  1225. X                    /* prepare to start again */
  1226. X        fclose(fp);
  1227. X    } while (file = strtok((char *) NULL, " \t"));
  1228. X
  1229. X    /*
  1230. X     * The end of batch markers... For modem7 it's an ACK and EOT, for
  1231. X     * ymodem, it's an empty block 0.
  1232. X     */
  1233. X    switch (type) {
  1234. X        case MODEM7:
  1235. X            if (code = rcv_first(win, default_err))
  1236. X                return(code +1);
  1237. X            putc_line(ACK);
  1238. X            putc_line(EOT);
  1239. X            beep();
  1240. X            wrefresh(win);
  1241. X            break;
  1242. X        case YMODEM:
  1243. X        case YMODEM_G:
  1244. X            if (code = rcv_first(win, default_err))
  1245. X                return(code +1);
  1246. X
  1247. X            if (code = send_ymodem(win, "", 0L))
  1248. X                return(code +1);
  1249. X            beep();
  1250. X            wrefresh(win);
  1251. X            break;
  1252. X        default:
  1253. X            break;
  1254. X    }
  1255. X    return(0);
  1256. X}
  1257. X
  1258. X/*
  1259. X * Wait for the first character to start the transmission.  This first
  1260. X * character also sets the crc/checksum method.  Returns the standard
  1261. X * error codes, or 0 on success.  The variable err_method is global.
  1262. X */
  1263. X
  1264. Xstatic int
  1265. Xrcv_first(win, default_err)
  1266. XWINDOW *win;
  1267. Xint default_err;
  1268. X{
  1269. X    int i, err_count;
  1270. X    unsigned int sleep();
  1271. X    void cancel_xfer();
  1272. X
  1273. X    err_count = 0;
  1274. X    while (err_count < MAX_ERRORS) {
  1275. X
  1276. X                    /* scan the keyboard for abort */
  1277. X        if (wgetch(win) == ESC) {
  1278. X            beep();
  1279. X            clear_line(win, 12, 24, TRUE);
  1280. X            waddstr(win, "ABORTED");
  1281. X            wrefresh(win);
  1282. X            cancel_xfer(UP_LOAD);
  1283. X            sleep(3);
  1284. X            return(ABORT);
  1285. X        }
  1286. X                    /* scan the TTY line */
  1287. X        i = getc_line(10);
  1288. X#ifdef DEBUG
  1289. X        fprintf(stderr, "rcv_first: got \"%c\", %02x, %03o, %d\n", i, i, i, i);
  1290. X#endif /* DEBUG */
  1291. X        switch (i) {
  1292. X            case -1:    /* timed out */
  1293. X                clear_line(win, 12, 24, TRUE);
  1294. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  1295. X                err_count++;
  1296. X                break;
  1297. X            case NAK:    /* checksum marker */
  1298. X                if (default_err == CHECKSUM || default_err == CRC_CHECKSUM) {
  1299. X                    mvwaddstr(win, 5, 24, "CHECKSUM");
  1300. X                    err_method = CHECKSUM;
  1301. X                    return(0);
  1302. X                }
  1303. X                err_count++;
  1304. X                break;
  1305. X            case 'C':    /* CRC marker */
  1306. X                if (default_err == CRC_CHECKSUM || default_err == CRC) {
  1307. X                    mvwaddstr(win, 5, 24, "CRC");
  1308. X                    err_method = CRC;
  1309. X                    return(0);
  1310. X                }
  1311. X                err_count++;
  1312. X                break;
  1313. X            case 'G':    /* ymodem-g marker */
  1314. X                if (default_err == NONE) {
  1315. X                    mvwaddstr(win, 5, 24, "NONE");
  1316. X                    err_method = NONE;
  1317. X                    return(0);
  1318. X                }
  1319. X                err_count++;
  1320. X                break;
  1321. X            case CAN:    /* two CAN's and you're out! */
  1322. X                if (getc_line(2) == CAN) {
  1323. X                    beep();
  1324. X                    clear_line(win, 12, 24, TRUE);
  1325. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  1326. X                    wrefresh(win);
  1327. X                    return(CANCEL);
  1328. X                }
  1329. X                err_count++;
  1330. X                break;
  1331. X            default:
  1332. X                clear_line(win, 12, 24, TRUE);
  1333. X                waddstr(win, "BAD HEADER");
  1334. X                err_count++;
  1335. X                break;
  1336. X        }
  1337. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  1338. X        wrefresh(win);
  1339. X    }
  1340. X                    /* failed to get it right? */
  1341. X    beep();
  1342. X    clear_line(win, 12, 24, TRUE);
  1343. X    wattrstr(win, A_BOLD, "TIMED OUT");
  1344. X    wrefresh(win);
  1345. X    return(ERROR);
  1346. X}
  1347. X
  1348. X/*
  1349. X * Send a block of data, scan the keyboard for a user abort, and check
  1350. X * the return codes from the host.  Returns standard error codes or 0
  1351. X * on success.
  1352. X */
  1353. X
  1354. Xint
  1355. Xsend_block(win, blk, packet)
  1356. XWINDOW *win;
  1357. Xunsigned char *blk;
  1358. Xunsigned int packet;
  1359. X{
  1360. X    extern int fd;
  1361. X    int i, err_count;
  1362. X    void cancel_xfer();
  1363. X
  1364. X    err_count = 0;
  1365. X    mvwaddstr(win, 10, 24, "0 ");
  1366. X
  1367. X    while (err_count < MAX_ERRORS) {
  1368. X                    /* write the block */
  1369. X        write(fd, (char *) blk, packet);
  1370. X                    /* scan the keyboard */
  1371. X        if (wgetch(win) == ESC) {
  1372. X            beep();
  1373. X            clear_line(win, 12, 24, TRUE);
  1374. X            waddstr(win, "ABORTED");
  1375. X            wrefresh(win);
  1376. X            cancel_xfer(UP_LOAD);
  1377. X            sleep(3);
  1378. X            return(ABORT);
  1379. X        }
  1380. X                    /* ymodem-g doesn't need ACKs */
  1381. X        if (err_method == NONE)
  1382. X            return(0);
  1383. X                    /* wait for acknowledge */
  1384. X        i = getc_line(10);
  1385. X#ifdef DEBUG
  1386. X        fprintf(stderr, "send_block: got \"%c\", %02x, %03o, %d\n", i, i, i, i);
  1387. X#endif /* DEBUG */
  1388. X        switch (i) {
  1389. X            case -1:    /* timed out */
  1390. X                clear_line(win, 12, 24, TRUE);
  1391. X                waddstr(win, "NO RESPONSE");
  1392. X                err_count++;
  1393. X                tot_err++;
  1394. X                break;
  1395. X            case ACK:    /* Hooray!! we got it */
  1396. X                return(0);
  1397. X            case NAK:    /* show our disappointment... */
  1398. X                clear_line(win, 12, 24, TRUE);
  1399. X                if (err_method == CRC)
  1400. X                    waddstr(win, "CRC FAILED");
  1401. X                else
  1402. X                    waddstr(win, "CHECKSUM FAILED");
  1403. X                err_count++;
  1404. X                tot_err++;
  1405. X                break;
  1406. X            case CAN:    /* two CAN's and you're out! */
  1407. X                if (getc_line(2) == CAN) {
  1408. X                    beep();
  1409. X                    clear_line(win, 12, 24, TRUE);
  1410. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  1411. X                    wrefresh(win);
  1412. X                    return(CANCEL);
  1413. X                }
  1414. X                /* fall thru... */
  1415. X            default:
  1416. X                clear_line(win, 12, 24, TRUE);
  1417. X                waddstr(win, "RESENDING");
  1418. X                err_count++;
  1419. X                tot_err++;
  1420. X                break;
  1421. X        }
  1422. X                    /* flush any pending garbage */
  1423. X        tty_flush(fd, 0);
  1424. X
  1425. X        mvwprintw(win, 10, 24, "%-2d", err_count);
  1426. X        mvwprintw(win, 11, 24, "%-3d", tot_err);
  1427. X        wrefresh(win);
  1428. X    }
  1429. X                    /* failed to get it right */
  1430. X    beep();
  1431. X    clear_line(win, 12, 24, TRUE);
  1432. X    wattrstr(win, A_BOLD, "TOO MANY ERRORS");
  1433. X    wrefresh(win);
  1434. X    cancel_xfer(UP_LOAD);
  1435. X    return(ERROR);
  1436. X}
  1437. SHAR_EOF
  1438. if test 11650 -ne "`wc -c < 'x_send.c'`"
  1439. then
  1440.     echo shar: "error transmitting 'x_send.c'" '(should have been 11650 characters)'
  1441. fi
  1442. fi
  1443. echo shar: "extracting 'x_win.c'" '(2317 characters)'
  1444. if test -f 'x_win.c'
  1445. then
  1446.     echo shar: "will not over-write existing file 'x_win.c'"
  1447. else
  1448. sed 's/^X//' << \SHAR_EOF > 'x_win.c'
  1449. X/*
  1450. X * Display the file transfer window, and invoke the transfer protocol.
  1451. X */
  1452. X
  1453. X#include <stdio.h>
  1454. X#include <curses.h>
  1455. X#include "config.h"
  1456. X#include "dial_dir.h"
  1457. X#include "misc.h"
  1458. X#include "xmodem.h"
  1459. X
  1460. Xvoid
  1461. Xxfer_win(list, up, type)
  1462. Xchar *list;
  1463. Xint up, type;
  1464. X{
  1465. X    extern int fd;
  1466. X    WINDOW *xf_win, *newwin();
  1467. X    int ack_error, fast;
  1468. X    void xmodem_mode(), input_off(), line_set(), st_line();
  1469. X
  1470. X    touchwin(stdscr);
  1471. X    refresh();
  1472. X    st_line("");
  1473. X
  1474. X    xf_win = newwin(15, 44, 2, 30);
  1475. X    /*
  1476. X     * This window should be in the non-blocking mode, so we can
  1477. X     * scan the keyboard for input while transferring a file.
  1478. X     */
  1479. X    nodelay(xf_win, TRUE);
  1480. X                    /* basic window stuff */
  1481. X    mvwaddstr(xf_win, 2, 14, "Protocol:");
  1482. X    mvwaddstr(xf_win, 3, 13, "File name:");
  1483. X    mvwaddstr(xf_win, 4, 13, "File size:");
  1484. X    mvwaddstr(xf_win, 5, 4, "Error check method:");
  1485. X    mvwaddstr(xf_win, 6, 5, "Est transfer time:");
  1486. X    mvwaddstr(xf_win, 7, 11, "Block count:");
  1487. X    mvwaddstr(xf_win, 8, 6, "Percent complete:");
  1488. X    mvwaddstr(xf_win, 9, 5, "Bytes transferred:");
  1489. X    mvwaddstr(xf_win, 10, 5, "Errors this block:");
  1490. X    mvwaddstr(xf_win, 11, 5, "Total error count:");
  1491. X    mvwaddstr(xf_win, 12, 10, "Last message: NONE");
  1492. X    box(xf_win, VERT, HORZ);
  1493. X
  1494. X    if (up)
  1495. X        mvwattrstr(xf_win, 0, 17, A_BOLD, " Uploading ");
  1496. X    else
  1497. X        mvwattrstr(xf_win, 0, 16, A_BOLD, " Downloading ");
  1498. X
  1499. X    mvwaddstr(xf_win, 14, 11, " Press <ESC> to abort ");
  1500. X    wrefresh(xf_win);
  1501. X                    /* fix up the terminal mode */
  1502. X    input_off();
  1503. X    xmodem_mode(fd);
  1504. X
  1505. X    /*
  1506. X     * Is your terminal slower than the xfer baud rate?  For example:
  1507. X     * I'm at home with my PC and 1200 baud modem; I call my system
  1508. X     * at work so I can use their 2400 baud modems to call some other
  1509. X     * system.  In this case, I don't wanna spend too much time updating
  1510. X     * my screen at 1200 baud, when I'm transferring the file at 2400 baud.
  1511. X     */
  1512. X    fast = 0;
  1513. X
  1514. X    if (my_speed() >= dir->baud[dir->d_cur])
  1515. X        fast++;
  1516. X
  1517. X    if (up)
  1518. X        ack_error = send_xmodem(xf_win, list, type, fast);
  1519. X    else
  1520. X        ack_error = rcv_xmodem(xf_win, list, type, fast);
  1521. X
  1522. X    nodelay(xf_win, FALSE);
  1523. X                    /* prompt for a key on errors */
  1524. X    if (ack_error) {
  1525. X        beep();
  1526. X        clear_line(xf_win, 13, 9, TRUE);
  1527. X        wattrstr(xf_win, A_BOLD, "Press any key to continue");
  1528. X        wrefresh(xf_win);
  1529. X        wgetch(xf_win);
  1530. X    }
  1531. X    werase(xf_win);
  1532. X    wrefresh(xf_win);
  1533. X    delwin(xf_win);
  1534. X                    /* undo what xmodem_mode() did */
  1535. X    line_set();
  1536. X    return;
  1537. X}
  1538. SHAR_EOF
  1539. if test 2317 -ne "`wc -c < 'x_win.c'`"
  1540. then
  1541.     echo shar: "error transmitting 'x_win.c'" '(should have been 2317 characters)'
  1542. fi
  1543. fi
  1544. echo shar: "extracting 'xmodem.c'" '(6553 characters)'
  1545. if test -f 'xmodem.c'
  1546. then
  1547.     echo shar: "will not over-write existing file 'xmodem.c'"
  1548. else
  1549. sed 's/^X//' << \SHAR_EOF > 'xmodem.c'
  1550. X/*
  1551. X * Miscellaneous routines to support the xmodem file transfer protocols.
  1552. X */
  1553. X
  1554. X#define TMP_FILE    "trunXXXXXX"
  1555. X
  1556. X#include <stdio.h>
  1557. X#include <signal.h>
  1558. X#include <sys/types.h>
  1559. X#include <sys/stat.h>
  1560. X#include "config.h"
  1561. X#include "misc.h"
  1562. X#include "param.h"
  1563. X#include "xmodem.h"
  1564. X
  1565. X#ifdef BSD
  1566. X#include <setjmp.h>
  1567. Xjmp_buf gl_buf, rl_buf;
  1568. X#endif /* BSD */
  1569. X
  1570. X/*
  1571. X * Calculate the CRC for the given buffer
  1572. X */
  1573. X
  1574. Xunsigned short
  1575. Xcalc_crc(buf, len)
  1576. Xunsigned char *buf;
  1577. Xint len;
  1578. X{
  1579. X    register int i;
  1580. X    unsigned short crc;
  1581. X    static unsigned short crctab[256] = {
  1582. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  1583. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  1584. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  1585. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  1586. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  1587. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  1588. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  1589. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  1590. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  1591. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  1592. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  1593. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  1594. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  1595. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  1596. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  1597. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  1598. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  1599. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  1600. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  1601. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  1602. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  1603. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  1604. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  1605. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  1606. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  1607. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  1608. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  1609. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  1610. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  1611. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  1612. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  1613. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
  1614. X
  1615. X    crc = 0;
  1616. X    for (i=0; i<len; i++)
  1617. X        crc = (crc<<8) ^ crctab[(crc>>8) ^ *buf++];
  1618. X
  1619. X    return(crc);
  1620. X}
  1621. X
  1622. X/*
  1623. X * Calculate the checksum for the given buffer.
  1624. X */
  1625. X
  1626. Xunsigned char
  1627. Xcalc_sum(buf, len)
  1628. Xunsigned char *buf;
  1629. Xint len;
  1630. X{
  1631. X    unsigned char sum;
  1632. X
  1633. X    sum = 0;
  1634. X    while (--len >= 0)
  1635. X        sum += *buf++;
  1636. X
  1637. X    return(sum);
  1638. X}
  1639. X
  1640. X/*
  1641. X * Get a single character from the line with a specified time-out period
  1642. X * in seconds.  If the function times-out, it returns a -1.
  1643. X */
  1644. X
  1645. Xstatic int gl_flag;
  1646. X
  1647. Xint
  1648. Xgetc_line(sec)
  1649. Xunsigned int sec;
  1650. X{
  1651. X    extern int fd;
  1652. X    int gl_force();
  1653. X    char c;
  1654. X    unsigned int alarm();
  1655. X
  1656. X    signal(SIGALRM, gl_force);
  1657. X    gl_flag = 0;
  1658. X
  1659. X    alarm(sec);
  1660. X
  1661. X#ifdef BSD
  1662. X    if (setjmp(gl_buf))
  1663. X        return(-1);
  1664. X#endif /* BSD */
  1665. X
  1666. X    if (read(fd, &c, 1) <= 0) {
  1667. X        alarm(0);
  1668. X        return(-1);
  1669. X    }
  1670. X    if (gl_flag)
  1671. X        return(-1);
  1672. X    alarm(0);
  1673. X    return(c & 0xff);
  1674. X}
  1675. X
  1676. X/* ARGSUSED */
  1677. Xstatic int
  1678. Xgl_force(dummy)
  1679. Xint dummy;
  1680. X{
  1681. X#ifdef BSD
  1682. X    longjmp(gl_buf, 1);
  1683. X#else /* BSD */
  1684. X    signal(SIGALRM, gl_force);
  1685. X    gl_flag = 1;
  1686. X#endif /* BSD */
  1687. X}
  1688. X
  1689. X/*
  1690. X * Same as above, but reads a bunch of characters.  The return code is
  1691. X * now just a success/fail indicator.
  1692. X */
  1693. X
  1694. Xstatic int rl_flag;
  1695. X
  1696. Xint
  1697. Xfread_line(buf, len, sec)
  1698. Xunsigned char *buf;
  1699. Xunsigned int len, sec;
  1700. X{
  1701. X    extern int fd;
  1702. X    int n, rl_force();
  1703. X    unsigned int try, alarm();
  1704. X
  1705. X    signal(SIGALRM, rl_force);
  1706. X    rl_flag = 0;
  1707. X
  1708. X    alarm(sec);
  1709. X    while (len) {
  1710. X                    /* read at most CLIST_SIZ chars */
  1711. X        try = (len > CLIST_SIZ) ? CLIST_SIZ : len;
  1712. X#ifdef BSD
  1713. X        if (setjmp(rl_buf))
  1714. X            return(-1);
  1715. X#endif /* BSD */
  1716. X        if ((n = read(fd, (char *) buf, try)) <= 0) {
  1717. X            alarm(0);
  1718. X            return(-1);
  1719. X        }
  1720. X        if (rl_flag)
  1721. X            return(-1);
  1722. X        len -= n;
  1723. X        buf = buf + n;
  1724. X    }
  1725. X    alarm(0);
  1726. X    return(0);
  1727. X}
  1728. X
  1729. X/* ARGSUSED */
  1730. Xstatic int
  1731. Xrl_force(dummy)
  1732. Xint dummy;
  1733. X{
  1734. X#ifdef BSD
  1735. X    longjmp(rl_buf, 1);
  1736. X#else /* BSD */
  1737. X    signal(SIGALRM, rl_force);
  1738. X    rl_flag = 1;
  1739. X#endif /* BSD */
  1740. X}
  1741. X
  1742. X/*
  1743. X * Put a character on the TTY line.  This serves no useful purpose other
  1744. X * than making the code look pretty.
  1745. X */
  1746. X
  1747. Xint
  1748. Xputc_line(c)
  1749. Xunsigned char c;
  1750. X{
  1751. X    extern int fd;
  1752. X
  1753. X    return(write(fd, (char *) &c, 1));
  1754. X}
  1755. X
  1756. X/*
  1757. X * Cancel the file transfer.  Send several ^X's to the remote, followed
  1758. X * by an equal number of backspaces (in case they have already aborted and
  1759. X * we're really at the command line).
  1760. X */
  1761. X
  1762. Xvoid
  1763. Xcancel_xfer(up)
  1764. Xint up;
  1765. X{
  1766. X    extern char file_name[15];
  1767. X
  1768. X    if (!up && !strcmp(param->abort, "DELETE"))
  1769. X        unlink(file_name);
  1770. X
  1771. X    putc_line(CAN);
  1772. X    putc_line(CAN);
  1773. X    putc_line(CAN);
  1774. X    putc_line(BS);
  1775. X    putc_line(BS);
  1776. X    putc_line(BS);
  1777. X    return;
  1778. X}
  1779. X
  1780. X/*
  1781. X * Shorten a file to a predetermined length.  Used to remove the ^Z
  1782. X * padding from the end of files.  (Heaven help us, if one day a binary
  1783. X * file actually has ^Z's as part of the end of the file).
  1784. X */
  1785. X
  1786. Xint
  1787. Xfix_length(file, len)
  1788. Xchar *file;
  1789. Xlong len;
  1790. X{
  1791. X    FILE *fp, *tempfp, *my_fopen();
  1792. X    register int num;
  1793. X    char *mktemp(), tempfile[128], buf[BUFSIZ], *strcpy();
  1794. X    char *s, *strrchr(), *strcat();
  1795. X    struct stat stbuf;
  1796. X
  1797. X    if (stat(file, &stbuf) < 0)
  1798. X        return(1);
  1799. X                    /* see if we have any work to do */
  1800. X    if (len >= stbuf.st_size)
  1801. X        return(0);
  1802. X
  1803. X    if (!(fp = my_fopen(file, "r")))
  1804. X        return(1);
  1805. X
  1806. X    /*
  1807. X     * The temporary file should be in the same directory as the
  1808. X     * file being received because otherwise we'd have no way of
  1809. X     * guaranteeing they would be in the same file system.  (Hard
  1810. X     * links across different file systems aren't allowed).
  1811. X     */
  1812. X    strcpy(tempfile, file);
  1813. X    if (s = strrchr(tempfile, '/'))
  1814. X        *++s = '\0';
  1815. X    else
  1816. X        strcpy(tempfile, "./");
  1817. X
  1818. X    strcat(tempfile, TMP_FILE);
  1819. X    mktemp(tempfile);
  1820. X
  1821. X    if (!(tempfp = my_fopen(tempfile, "w"))) {
  1822. X        fclose(fp);
  1823. X        return(1);
  1824. X    }
  1825. X
  1826. X    while (len != 0L) {
  1827. X        num = (len > BUFSIZ) ? BUFSIZ : len;
  1828. X        fread(buf, sizeof(char), num, fp);
  1829. X        if (fwrite(buf, sizeof(char), num, tempfp) != num) {
  1830. X            fclose(fp);
  1831. X            fclose(tempfp);
  1832. X            return(1);
  1833. X        }
  1834. X        len = len - (unsigned int) num;
  1835. X    }
  1836. X
  1837. X    fclose(fp);
  1838. X    fclose(tempfp);
  1839. X
  1840. X    if (unlink(file) < 0)
  1841. X        return(1);
  1842. X
  1843. X    if (link(tempfile, file) < 0)
  1844. X        return(1);
  1845. X
  1846. X    if (unlink(tempfile) < 0)
  1847. X        return(1);
  1848. X
  1849. X    return(0);
  1850. X}
  1851. SHAR_EOF
  1852. if test 6553 -ne "`wc -c < 'xmodem.c'`"
  1853. then
  1854.     echo shar: "error transmitting 'xmodem.c'" '(should have been 6553 characters)'
  1855. fi
  1856. fi
  1857. echo shar: "extracting 'xmodem.h'" '(561 characters)'
  1858. if test -f 'xmodem.h'
  1859. then
  1860.     echo shar: "will not over-write existing file 'xmodem.h'"
  1861. else
  1862. sed 's/^X//' << \SHAR_EOF > 'xmodem.h'
  1863. X/*
  1864. X * Definitions for the xmodem stuff.
  1865. X */
  1866. X
  1867. X#define MAX_ERRORS    10
  1868. X
  1869. X#define SOH        1
  1870. X#define STX        2
  1871. X#define EOT        4
  1872. X#define ACK        6
  1873. X#define NAK        21
  1874. X#define CAN        24
  1875. X#define CTRLZ        26
  1876. X
  1877. X#define NUM_INTERNAL    6
  1878. X#define XMODEM        0
  1879. X#define XMODEM_1k    1
  1880. X#define MODEM7        2
  1881. X#define YMODEM        3
  1882. X#define YMODEM_G    4
  1883. X#define XASCII        5
  1884. X#define EXT_1        6
  1885. X#define EXT_2        7
  1886. X#define EXT_3        8
  1887. X#define EXT_MANUAL    9
  1888. X
  1889. X#define ABORT        (-1)
  1890. X#define ERROR        (-2)
  1891. X#define CANCEL        (-3)
  1892. X
  1893. X#define CHECKSUM    0
  1894. X#define CRC_CHECKSUM    1
  1895. X#define CRC        2
  1896. X#define NONE        3
  1897. X
  1898. X#define DOWN_LOAD    0
  1899. X#define UP_LOAD        1
  1900. SHAR_EOF
  1901. if test 561 -ne "`wc -c < 'xmodem.h'`"
  1902. then
  1903.     echo shar: "error transmitting 'xmodem.h'" '(should have been 561 characters)'
  1904. fi
  1905. fi
  1906. exit 0
  1907. #    End of shell archive
  1908.  
  1909.  
  1910.